package cn.silver.module.monitor.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.json.JSONObject;
import cn.silver.framework.core.utils.StringUtils;
import cn.silver.framework.openapi.model.Result;
import cn.silver.framework.web.controller.ApiController;
import cn.silver.module.monitor.bean.CacheListInfoVo;
import cn.silver.module.monitor.bean.RedisBean;
import cn.silver.module.monitor.bean.RedisCommandBean;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.spring.data.connection.RedissonConnectionFactory;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * 缓存监控
 *
 * @author Lion Li
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@Tag(name = "Redis缓存管理")
@RequestMapping("/monitor/cache")
public class CacheController extends ApiController {

    private final RedissonConnectionFactory connectionFactory;

    /**
     * 获取缓存监控列表
     */
    @GetMapping("")
    @Operation(summary = "查询缓存列表")
    @SaCheckPermission("monitor:cache:list")
    public Result<CacheListInfoVo> page() throws Exception {
        RedisConnection connection = connectionFactory.getConnection();
        Properties commandStats = connection.commands().info("commandstats");
        List<Map<String, String>> pieList = new ArrayList<>();
        if (commandStats != null) {
            commandStats.stringPropertyNames().forEach(key -> {
                Map<String, String> data = new HashMap<>(2);
                String property = commandStats.getProperty(key);
                data.put("name", StringUtils.removeStart(key, "cmdstat_"));
                data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
                pieList.add(data);
            });
        }
        CacheListInfoVo infoVo = new CacheListInfoVo();
        infoVo.setInfo(connection.commands().info());
        infoVo.setDbSize(connection.commands().dbSize());
        infoVo.setCommandStats(pieList);
        return Result.ok(infoVo);
    }

    @GetMapping("/one")
    @Operation(summary = "查询缓存基本信息")
    @SaCheckPermission("monitor:cache:list")
    public Result<RedisBean> getInfo() {
        RedisConnection connection = connectionFactory.getConnection();
        RedisBean bean = new RedisBean();
        bean.setDbSize(connection.commands().dbSize());
        log.info("redis info:{}", connection.commands().info());
        bean.reload(connection.commands().info());
        return Result.ok(bean);
    }

    @GetMapping("/memory")
    @Operation(summary = "查询缓存基本信息")
    @SaCheckPermission("monitor:cache:list")
    public Result<JSONObject> getMemeory() throws Exception {
        RedisConnection connection = connectionFactory.getConnection();
        JSONObject result = new JSONObject();
        result.set("start", connection.commands().info().getProperty("used_memory_startup"));
        result.set("used", connection.commands().info().getProperty("used_memory_rss"));
        result.set("max", connection.commands().info().getProperty("maxmemory"));
        if (result.getLong("max") == 0L) {
            result.set("max", "");
        }
        return Result.ok(result);
    }

    @GetMapping("/command")
    @Operation(summary = "查询缓存基本信息")
    @SaCheckPermission("monitor:cache:list")
    public Result<List<RedisCommandBean>> getCommand() throws Exception {
        RedisConnection connection = connectionFactory.getConnection();
        Properties commandStats = connection.commands().info("commandstats");
        log.info("redis commands:{}", commandStats);
        List<RedisCommandBean> pieList = new ArrayList<>();
        if (commandStats != null) {
            commandStats.stringPropertyNames().forEach(key -> {
                RedisCommandBean data = new RedisCommandBean();
                String property = commandStats.getProperty(key);
                data.setName(StringUtils.removeStart(key, "cmdstat_"));
                data.setValue(Integer.valueOf(StringUtils.substringBetween(property, "calls=", ",usec")));
                pieList.add(data);
            });
        }
        return Result.ok(pieList);
    }
}
